package com.hibase.core.timezone.config;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.hibase.common.entity.User;
import com.hibase.common.util.UserContext;
import com.hibase.core.timezone.annotation.HiBaseTimezone;
import com.hibase.core.timezone.constant.TimezoneContant;
import com.hibase.core.timezone.util.TimezoneUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.TimeZone;

/**
 * TODO
 * 全局requsetBody 时区处理
 *
 * @author chenfeng
 * @version 1.0
 * @date 2020/10/14 9:59
 */
@ControllerAdvice
@Slf4j
public class TimezoneRequestBodyAdvice implements RequestBodyAdvice {

    @Autowired
    private TimezoneUtil timezoneUtil;

    //是否开启时区
    @Value("${hibase.timezone.enable:true}")
    private Boolean enableTimezone;

    @Override
    public boolean supports(MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
        //只处理RequestBody
        // 未登录 不需要
        User user = UserContext.get();
        if (ObjectUtil.isEmpty(user)) {
            return false;
        }
        //类中必须存在时区注解
        Field[] fs = aClass.getDeclaredFields();
        boolean match = Arrays.asList(fs).stream().anyMatch(field -> field.isAnnotationPresent(HiBaseTimezone.class));
        // 只转换 requestBody
        return enableTimezone&&match&&methodParameter.hasParameterAnnotation(
                RequestBody.class);
    }

    @Override
    public HttpInputMessage beforeBodyRead(HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) throws IOException {
        return httpInputMessage;
    }

    @Override
    public Object afterBodyRead(Object body, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
        //将用户所在的时区转换为系统的时区
        log.info("-----------------------------------------------");
        log.info("请求体时区转换时间开始");
        handleTimeZone(body);
        log.info("请求体时区转换时间结束");
        log.info("-----------------------------------------------");
        return body;
    }


    @Override
    public Object handleEmptyBody(Object body, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
        return body;
    }

    /**
     * 处理时区  用户时区转到 系统时区
     *
     * @param body
     */
    private void handleTimeZone(Object body) {
        //当前用户时区
        String timeZone = timezoneUtil.getCurrentTimeZone();

        //当前系统时区
        Integer target = timezoneUtil.getSystemTimeZone(TimeZone.getDefault().getID());
        timeZone = StrUtil.removePrefix(timeZone, TimezoneContant.PREFIX);
        timezoneUtil.handleTimeZoneByDetail(body, Integer.valueOf(timeZone), target);
    }
}
